/*******************************************************************************
 * Copyright (c) 2002,2003 David Corbin and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 *
 * Contributors: David Corbin - initial implementation - ALL access to perforce
 * server should be through this interface. - added moveFile method Boris
 * Pruessmann - Migrated functionality from from IClientApi to IPerforceServer
 * to achieve api separation. Boris Pruessmann - Changed signature of reopen to
 * support IFileType.
 ******************************************************************************/
package net.sourceforge.perforce.core.api;

import java.io.InputStream;
import java.util.List;

import net.sourceforge.perforce.api.CharSetEnum;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.internal.api.ChangeSpec;
import net.sourceforge.perforce.core.internal.api.FolderRepositoryRelation;
import net.sourceforge.perforce.core.internal.model.P4Label;
import net.sourceforge.perforce.core.resources.IChangelist;
import net.sourceforge.perforce.core.resources.RemoteFile;
import net.sourceforge.perforce.core.resources.RemoteResource;
import net.sourceforge.perforce.core.syncinfo.FolderSyncInfo;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.team.IResourceTree;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;

/**
 * This interface describes the API used to access PerforceServer objects.
 *
 * @version $Revision: 494 $
 * @author <a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 *
 *         TODO: Check whether all thos methods need to be on the server
 *         interface, think about introducing a IPerforceProvider interface like
 *         they did with CVS.
 *
 *         TODO: Use of IProgressMonitor.
 *
 *         TODO: Better typing for the parameters of most methods. String is not
 *         convenient.
 *
 *         TODO: Investigate change from throwing exceptions to passing status
 *         objects.
 */
public interface IPerforceServer {
  //----------------------------------------------------------------------------
  // ------- Constants

  /** Constant: Indicates that resolve should re-resolve already resolved files */
  int RESOLVE_FORCE = 0x01;
  /** Constant: Indicates that resolve should perform textual merge on binaries */
  int RESOLVE_MERGE_BINARY = 0x02;
  /** Constant: Indicates that resolve should not touch any file */
  int RESOLVE_SIMULATE = 0x04;
  /** Constant: Bit mask of valid resolve options */
  int RESOLVE_OPTIONS = RESOLVE_FORCE | RESOLVE_MERGE_BINARY | RESOLVE_SIMULATE;

  //----------------------------------------------------------------------------
  // --------- Methods

  /**
   * Returns the toplevel members of the server.
   *
   * @param monitor for progress feedback.
   * @return the top level members of the server.
   *
   * @throws PerforceException in case of an error.
   */
  RemoteResource[] members(IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to retrieve the IFile that corresponds to the given
   * filename (in any of the supported syntaxes).
   *
   * @param filename path of the file.
   * @return the corresponding IFile or null.
   *
   * @throws PerforceException in case of an error.
   */
  IFile getFile(String filename) throws PerforceException;

  /**
   * Call this method to retrieve the unique name of the server. This will be a
   * combination of P4PORT, P4CLIENT and P4USER.
   *
   * @return the unique server name.
   */
  String getUniqueName();

  /**
   * This method returns the P4PORT value that is associated with this server.
   *
   * @return the P4PORT value.
   */
  String getPort();

  /**
   * This method sets the server's P4PORT value.
   *
   * @param port the P4PORT value.
   */
  void setPort(String port);

  /**
   * This method returns the P4CLIENT value that is associated with this server.
   *
   * @return the P4CLIENT value.
   */
  String getClient();

  /**
   * Called to set the P4CLIENT value of the server.
   *
   * @param client the P4CLIENT value.
   */
  void setClient(String client);

  /**
   * This method returns the P4HOST value that is associated with this server.
   *
   * @return the P4HOST value.
   */
  String getHost();

  /**
   * Call this method to set the P4HOST value that is associated with the
   * server.
   *
   * @param host the P4HOST value.
   */
  void setHost(String host);

  /**
   * Returns the value of the associated P4USER.
   *
   * @return the P4USER value.
   */
  String getUser();

  /**
   * Sets the associated P4USER value.
   *
   * @param user the P4USER value.
   */
  void setUser(String user);

  /**
   * Returns the value of the associated P4PASSWD.
   *
   * @return the P4PASSWD value.
   */
  String getPassword();

  /**
   * Called to set the associated P4PASSWD value.
   *
   * @param passwd the new P4PASSWD value.
   */
  void setPassword(String passwd);

  /**
   * Returns the value of the associated P4CHARSET.
   *
   * @return the P4CHARSET value.
   */
  CharSetEnum getCharset();

  /**
   * Sets the value of the P4CHARSET variable.
   *
   * @param charset the new charset value.
   */
  void setCharset(CharSetEnum charset);

  /**
   * Returns the address of the server.
   *
   * @return the server address.
   *
   * @throws PerforceException in case of an error.
   */
  String getServerAddress() throws PerforceException;

  /**
   * Returns the root of the server.
   *
   * @return the server root.
   *
   * @throws PerforceException in case of an error.
   */
  String getServerRoot() throws PerforceException;

  /**
   * Returns the root of the client on the local file system.
   *
   * @return the local Perforce client root.
   *
   * @throws PerforceException in case of an error.
   */
  IPath getClientRoot() throws PerforceException;

  /**
   * Returns the date as currently set on the server.
   *
   * @return the server date as string.
   *
   * @throws PerforceException in case of an error.
   */
  String getServerDate() throws PerforceException;

  /**
   * Call this method to retrieve the server version.
   *
   * @return the server version.
   *
   * @throws PerforceException in case of an error.
   */
  String getServerVersion() throws PerforceException;

  /**
   * Returns the server's license info.
   *
   * @return the license info.
   *
   * @throws PerforceException in case of an error.
   */
  String getServerLicense() throws PerforceException;

  /**
   * Call this method to check whether the given folder is under the perforce
   * root or not.
   *
   * @param folder the folder path.
   * @return object providing detailed information.
   */
  FolderRepositoryRelation determineFolderPosition(String folder);

  /**
   * Returns the client form for the configured client.
   *
   * @return the ClientForm.
   *
   * @throws PerforceException in case of an unexpected error.
   */
  IClientForm getClientForm() throws PerforceException;

  /**
   * Call this method to perform a perforce move of the given files.
   *
   * @param tree the resource tree containing source and destination.
   * @param src the file to move.
   * @param destination the operation's destination.
   * @param monitor for progress feedback,
   * @return true if we handled the move.
   */
  boolean moveFile(IResourceTree tree, IFile src, IFile destination, int updateFlags,
      IProgressMonitor monitor);

  /**
   * Call this method to validate the server instanec, that is: check whether a
   * connection to the server is possible with the given configuation.
   *
   * @param monitor for progress feedback.
   *
   * @throws PerforceException if it wasn't possible to connect to the server.
   */
  void validateConnection(IProgressMonitor monitor) throws PerforceException;

  // ---------------------------------------------------------------------------
  // Public P4 Methods

  /**
   * Call this method to add the given files to the control of perforce.
   *
   * @param fileNames array of filenames to be added.
   * @param monitor monitor for progress feedack or null.
   *
   * @throws PerforceException in case of an error.
   */
  void add(String[] fileNames, IProgressMonitor monitor) throws PerforceException;

  /**
   * Create a changelist description from the given changespec.
   *
   * @param changeSpec the changespec description.
   * @return the id of the newly created changelist.
   *
   * @throws PerforceException in case of an error.
   */
  Integer change(ChangeSpec changeSpec) throws PerforceException;

  /**
   * Reads a changelist specification.
   *
   * @param changelist the changelist number / id.
   * @return the specification of the given changelist.
   *
   * @throws PerforceException in case of an error.
   */
  IChangeResult change(Integer changelist) throws PerforceException;

  /**
   * Retrieves list of pending and submitted changelists.
   *
   * @param status either 'pending' or 'submitted'.
   * @param count number of entries to fetch.
   * @return array of changelist descriptions.
   *
   * @throws PerforceException in case of an error.
   */
  IChangesResult[] changes(String status, int count) throws PerforceException;

  /**
   * Retrieves list of known counters.
   *
   * @return object containing the values of all counters known to the server.
   *
   * @throws PerforceException in case of an error.
   */
  ICountersResult counters() throws PerforceException;

  /**
   * Opens the given filenames for delete.
   *
   * @param fileNames array of files to be oepned for delete.
   *
   * @throws PerforceException in case of an error.
   */
  void delete(String[] fileNames) throws PerforceException;

  /**
   * Call this method to retrieve a list of depots as defined on the server.
   *
   * @param monitor use for progress feedback.
   * @return array of depot names.
   *
   * @throws PerforceException in case of an error.
   */
  String[] depots(IProgressMonitor monitor) throws PerforceException;

  /**
   * Calls this method to retrieve a changelist description.
   *
   * @param changelist the changelist number.
   * @return a description of the given changelist.
   *
   * @throws PerforceException in case of an error.
   */
  IDescribeResult describe(Integer changelist) throws PerforceException;

  /**
   * Performs a 'p4 diff -sr' and returns a list of unchanged files.
   *
   * @param files array of files to check.
   * @return subset of files that do not differ from their server counterparts.
   *
   * @throws PerforceException in case of an error.
   */
  String[] diff(String[] files) throws PerforceException;

  /**
   * List subdirectories of a given depot directory.
   *
   * @param dir the name of the directory (might include wildcard)
   * @param monitor for progress feedback
   * @return array of FolderSyncInfo's.
   *
   * @throws PerforceException in case of an error.
   */
  FolderSyncInfo[] dirs(String dir, IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to open the given files for edit.
   *
   * @param fileNames array of filenames.
   * @param monitor the progress monitor.
   *
   * @throws PerforceException in case of an error.
   */
  void edit(String[] fileNames, IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to retrieve the history of the given remote file.
   *
   * @param remoteFile the remote file.
   * @param maxRevs number of revisions that we max. want to fetch.
   * @param follow true if we want to follow branches.
   * @return array of log entries.
   *
   * @throws PerforceException in case of an error.
   */
  ILogEntry[] filelog(RemoteFile remoteFile, int maxRevs, boolean follow) throws PerforceException;

  /**
   * Call this method to find all files matching the filespec.
   *
   * @param filespec the filespec.
   * @param monitor for progress feedback.
   * @return array of remote files.
   *
   * @throws PerforceException in case of an error.
   */
  RemoteFile[] findAllFiles(String filespec, IProgressMonitor monitor) throws PerforceException;

  /**
   * Tries to locat the specified resource.
   *
   * @param name name of the file or folder.
   * @param monitor the progress monitor.
   * @return the resource if found.
   *
   * @throws PerforceException in case of an error.
   */
  RemoteResource find(String name, IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to retrieve ResourceSyncInfo for the given file spec.
   *
   * @param file the name of the file (might include wildcard).
   * @param monitor the progress monitor.
   * @return array of ResourceSyncInfo.
   *
   * @throws PerforceException in case of an exception.
   */
  ResourceSyncInfo[] fstat(String file, IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to retrieve ResourceSyncInfo for a number of files.
   *
   * @param files array of files.
   * @param monitor the progress monitor.
   * @return array of ResourceSyncInfo.
   *
   * @throws PerforceException in case of an exception.
   */
  ResourceSyncInfo[] fstat(IFile[] files, IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to retrieve client/server information.
   *
   * @param monitor used for progress feedback.
   * @return the fetched info record.
   *
   * @throws PerforceException in case of an unexpected error.
   */
  IInfoResult info(IProgressMonitor monitor) throws PerforceException;

  /**
   * Call this method to perform an 'p4 integrate' on the given file.
   *
   * @param from the source of the integration.
   * @param to the destination of the integration.
   *
   * @throws PerforceException in case of an error.
   */
  void integrate(String from, String to) throws PerforceException;

  /**
   * Retrieves all labels currently known to the system.
   *
   * @return array of Labels
   *
   * @throws PerforceException in case of an error.
   */
  P4Label[] labels() throws PerforceException;

  /**
   * Retrieves the labels that contain the given fileSpec.
   *
   * @param fileSpec file spec specifying one or more files.
   * @return array of Labels
   *
   * @throws PerforceException in case of an error.
   */
  P4Label[] labels(String fileSpec) throws PerforceException;

  /**
   * Returns list of files opened for pending changelist.
   *
   * @param changelist the number of the changelist.
   * @return array of opened files.
   *
   * @throws PerforceException in case of an error.
   */
  IOpenedResult[] opened(IChangelist changelist) throws PerforceException;

  /**
   * Returns list of files opened for ...
   *
   * @param allClients get info for all clients.
   * @return array of opened files.
   *
   * @throws PerforceException in case of an error.
   */
  IOpenedResult[] opened(boolean allClients) throws PerforceException;

  /**
   * Called to retrieve an array of IOpenedResult records for the given file.
   *
   * @param file the file.
   * @return array of IOpenedResult.
   *
   * @throws PerforceException in case of an error.
   */
  IOpenedResult[] opened(IFile file) throws PerforceException;

  /**
   * Call this method to reopen the given files in the specified changelist.
   *
   * @param changelist the number of the target changelist.
   * @param fileType the new file type or null.
   * @param filenames array of filenames.
   * @param monitor for progress feedback.
   *
   * @throws PerforceException in case of an error.
   */
  void reopen(Integer changelist, IFileType fileType, IPath[] filenames, IProgressMonitor monitor)
      throws PerforceException;

  /**
   * Call this method to merge open files with other revisions.
   *
   * @param spec specification of the file to resolve.
   * @param resolveType indicates how to resolve the ginve spec.
   * @param options misc options to resolve operation.
   * @return array of resolve results.
   *
   * @throws PerforceException in case of an error.
   *
   *         TODO: Implement/Fix non-simulating mode.
   */
  IResolveResult[] resolve(String spec, ResolveTypeEnum resolveType, int options)
      throws PerforceException;

  /**
   * Checks whether the given file has been resolved or not.
   *
   * @param filename name of the file(s).
   * @return array of resolved results
   *
   * @throws PerforceException in case of an error.
   */
  IResolvedResult[] resolved(String filename) throws PerforceException;

  /**
   * Call this method to revert the given files.
   *
   * @param fileNames array of file names to revert.
   * @param monitor the progress monitor to use.
   *
   * @throws PerforceException in case of an error.
   */
  void revert(String[] fileNames, IProgressMonitor monitor) throws PerforceException;

  /**
   * Submits the given changespec.
   *
   * @param changeSpec describing the changelist.
   * @param monitor monitor for progress feedback.
   * @return composite submit result holding the status of the operation and the
   *         results.
   *
   * @throws PerforceException in case of an error.
   */
  ICompositeSubmitResult submit(ChangeSpec changeSpec, IProgressMonitor monitor)
      throws PerforceException;

  /**
   * Performs a 'p4 sync' based on the given path and revision spec.
   *
   * @param path the path specification.
   * @param revisionSpec the revision specification.
   * @param monitor used for progress feedback.
   * @return status of the operation.
   *
   * @throws PerforceException in case of an unexpected error.
   */
  IStatus sync(String path, String revisionSpec, IProgressMonitor monitor) throws PerforceException;

  /**
   * Performs a 'p4 sync' and adds the synced files to the list.
   *
   * @param path the path specification.
   * @param revisionSpec the revision specification.
   * @param syncedFileList [out] the synced files.
   * @param monitor used for progress feedback.
   * @return status of the operation.
   *
   * @throws PerforceException in case of an unexpected error.
   */
  IStatus sync(String path, String revisionSpec, List<IFile> syncedFileList,
      IProgressMonitor monitor) throws PerforceException;

  /**
   * Simulates a 'p4 sync' operation.
   *
   * @param syncSpec sync specification.
   * @param simulate has to be true for the moment.
   * @param monitor for progress feedback.
   * @return array of files that would be synced.
   *
   * @throws PerforceException in case of an unexpected error.
   *
   *         TODO: merge with sync(String)
   */
  String[] sync(String syncSpec, boolean simulate, IProgressMonitor monitor)
      throws PerforceException;

  /**
   * Performs a 'p4 print', result will be in form of an InputStream.
   *
   * @param depotFileName the name of the file.
   * @param revision the revision spec.
   * @return the InputStream.
   *
   * @throws PerforceException in case of an error.
   */
  InputStream print(String depotFileName, String revision) throws PerforceException;

  /**
   * Show how file names map through the client view.
   *
   * @param filename in any supported Perforce format (depot, client, local)
   * @return object containing the representations of the filename.
   *
   * @throws PerforceException in case of an error.
   */
  IWhereResult where(String filename) throws PerforceException;

  /**
   * Like where(String) but for multiple files.
   *
   * @param filenames array of filenames.
   * @return array of mappings.
   *
   * @throws PerforceException in case of an error.
   *
   * @see IPerforceServer#where(String)
   */
  IWhereResult[] where(String[] filenames) throws PerforceException;

  /**
   * Returns the mapping of the given resource.
   *
   * @param resource the resource.
   * @return the mapping.
   *
   * @throws PerforceException in case of an error.
   *
   * @see IPerforceServer#where(String)
   */
  IWhereResult where(IResource resource) throws PerforceException;

  /**
   * Indicates whether this server should be included when performing background
   * cache updates or not.
   *
   * @return true if this server should be included.
   */
  boolean shouldIncludeInBackgroundUpdates();

  /**
   * Includes or excludes the server from background updates based on the given
   * value.
   *
   * @param value true or false.
   */
  void setShouldIncludeInBackgroundUpdates(boolean value);

  /**
   * Called to delete the given changelist.
   *
   * @param changelist the changelist.
   *
   * @throws PerforceException in case of an error.
   */
  void deleteChangelist(IChangelist changelist) throws PerforceException;

  /**
   * Returns the id of the currently active changlist.
   *
   * @return the id of the currently active changelist.
   */
  Integer getActiveChangelistId();

  /**
   * Sets the id of the currently active changelist.
   *
   * @param changelistId id of the active changelist.
   */
  void setActiveChangelistId(Integer changelistId);
}
